package com.sky.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sky.constant.CacheConstants;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.context.BaseContext;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Category;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.exception.BaseException;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.mapper.DishFlavorMapper;
import com.sky.mapper.DishMapper;
import com.sky.result.PageResult;
import com.sky.service.CategoryService;
import com.sky.service.DishFlavorService;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 实现类
 *
 * @Author mr.lcc
 * @Data 2025/5/19 22:24
 */
@Service
@Slf4j
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private DishMapper dishMapper;

    @Autowired
    private DishFlavorService dishFlavorService;

    @Autowired
    private DishFlavorMapper dishFlavorMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    /**
     * 新增菜品
     *
     * @param dto
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveDish(DishDTO dto) {
        // 健壮性判断
        if (ObjectUtils.isEmpty(dto)) {
            throw new BaseException("新增参数为空");
        }

        // 删除缓存
        log.info("[DishServiceImpl]新增数据前删除的缓存key:{}", dto.getCategoryId());
        Long categoryId = dto.getCategoryId();
        String key = CacheConstants.DISH_LIST + categoryId;
        redisTemplate.delete(key);

        // 1.保存菜品数据
        Dish saveDish = new Dish();
        BeanUtils.copyProperties(dto, saveDish);
        this.save(saveDish);
        // 2.保存菜品口味数据
        List<DishFlavor> flavors = dto.getFlavors();
        if (!CollectionUtils.isEmpty(flavors)) {
            flavors.stream().forEach(dishFlavor -> {
                dishFlavor.setDishId(saveDish.getId());
            });
            dishFlavorService.saveBatch(flavors);
        }
    }

    /**
     * 菜品分页查询
     *
     * @param dto
     * @return
     */
    @Override
    public PageResult queryPage(DishPageQueryDTO dto) {
        if (ObjectUtils.isEmpty(dto)) {
            throw new BaseException("分页参数为空");
        }
        Page<Dish> page = new Page<>(dto.getPage(), dto.getPageSize());
        this.lambdaQuery()
                .eq(dto.getCategoryId() != null, Dish::getCategoryId, dto.getCategoryId())
                .eq(dto.getStatus() != null, Dish::getStatus, dto.getStatus())
                .like(dto.getName() != null, Dish::getName, dto.getName())
                .orderByDesc(Dish::getCreateTime)
                .page(page);

        List<Dish> dishList = page.getRecords();
        List<Category> categoryList = categoryService.list();

        // 构建categoryId -> categoryName 的映射，提高查询效率
        Map<Long, String> categoryMap = categoryList.stream()
                .collect(Collectors.toMap(Category::getId, Category::getName));

        // 遍历dishes并赋值，categoryName
        dishList.forEach(dish -> {
            Long categoryId = dish.getCategoryId();
            // 根据指定的 key 从 Map 中查找对应的值。如果找到了，就返回对应的值；如果没找到（即该 key 不存在或对应值为 null），则返回你指定的默认值 defaultValue。
            dish.setCategoryName(categoryMap.getOrDefault(categoryId, "未知分类"));
        });

        return new PageResult(page.getTotal(), page.getRecords());
    }

    /**
     * 批量删除菜品
     *
     * @param ids
     */
    @Transactional
    @Override
    public void deleteBatch(List<Long> ids) {
        //查询一下菜品表，看看售卖状态  ---dish
        log.info("[DishServiceImpl]删除的菜品数据id:{}", ids);
        for (Long id : ids) {
            Dish dish = dishMapper.selectById(id);
            if (dish.getStatus().equals(StatusConstant.ENABLE)) {
                //当前菜品在售状态，不能删除
                throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
            }
        }

        // 根据id查询数据清除缓存
        log.info("[DishServiceImpl]根据ids来删除缓存:{}", ids);
        if (CollUtil.isNotEmpty(ids)) {
            ids.stream().forEach(dish -> {
                Dish dishDate = this.getById(dish);
                String key = CacheConstants.DISH_LIST + dishDate.getCategoryId();
                redisTemplate.delete(key);
            });
        }

        // TODO 查询一下套餐菜品关系表，查看菜品是否被关联了，如果菜品被套餐关联，则不能删除

        log.info("[DishServiceImpl]删除菜品数据中");
        for (Long id : ids) {
            //从菜品表删除一条数据---dish
            dishMapper.deleteById(id);

            //从口味表删除当前菜品关联的口味数据----dish_flavor
            LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(DishFlavor::getDishId, id);
            dishFlavorService.remove(queryWrapper);
        }
        log.info("[DishServiceImpl]删除菜品数据成功");
    }

    /**
     * 根据id查询菜品和口味
     *
     * @param id
     * @return
     */
    @Override
    public DishVO getByIdWithFlavor(Long id) {
        // 根据id查询菜品表，获取菜品的基本信息
        Dish dish = dishMapper.selectById(id);

        //根据菜品id查询口味表，获取口味数据
        log.info("查询到的口味数据:{}", id);
        LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DishFlavor::getDishId, id);
        List<DishFlavor> dishFlavors = dishFlavorMapper.selectList(queryWrapper);

        //将查询到的两部分数据封装到VO中
        DishVO dishVO = new DishVO();
        BeanUtils.copyProperties(dish, dishVO);
        dishVO.setFlavors(dishFlavors);

        return dishVO;
    }

    /**
     * 根据id修改菜品
     *
     * @param dishDTO
     */
    @Transactional
    @Override
    public void updateWithFlavor(DishDTO dishDTO) {

        // 清除缓存
        Long categoryId = dishDTO.getCategoryId();
        String key = CacheConstants.DISH_LIST + categoryId;
        redisTemplate.delete(key);

        //1、删除原来的菜品关联的所有口味
        LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DishFlavor::getDishId, dishDTO.getId());
        dishFlavorMapper.delete(queryWrapper);

        //2、再重新添加一遍口味
        List<DishFlavor> flavors = dishDTO.getFlavors();
        for (DishFlavor flavor : flavors) {
            flavor.setDishId(dishDTO.getId());
        }

        if (flavors != null && flavors.size() > 0) {
            dishFlavorService.saveBatch(flavors);
        }

        //3、更新菜品表，根据id修改数据
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO, dish);
        dish.setUpdateTime(LocalDateTime.now());
        dish.setUpdateUser(BaseContext.getCurrentId());
        dishMapper.updateById(dish);
    }

    /**
     * 菜品起售停售
     *
     * @param status
     * @param id
     */
    @Override
    public void startOrStop(Integer status, Long id) {
        // 清除缓存
        Dish dishOne = this.getById(id);
        Long categoryId = dishOne.getCategoryId();
        String key = CacheConstants.DISH_LIST + categoryId;
        redisTemplate.delete(key);

        Dish dish = Dish.builder()
                .id(id)
                .status(status)
                .build();
        dishMapper.updateById(dish);
    }

    /**
     * 根据分类id查询菜品
     *
     * @param categoryId
     * @return
     */
    @Override
    public List<DishVO> listDish(Long categoryId) {

        // 缓存中的Key
       /* String key = CacheConstants.DISH_LIST + categoryId;
        List<String> range = redisTemplate.opsForList().range(key, 0, -1);
        if (CollUtil.isNotEmpty(range)) {
            return range.stream().map(s -> JSON.parseObject(s, DishVO.class)).collect(Collectors.toList());
        }*/

        // 根据分类id查询菜品数据
        List<Dish> dishList = dishMapper.selectList(new LambdaQueryWrapper<Dish>()
                .eq(Dish::getCategoryId, categoryId)
                .eq(Dish::getStatus, StatusConstant.ENABLE)
        );

        // 查询到的数据返回给前端进行数据处理
        List<DishVO> collect = dishList.stream()
                .map(dish -> {
                    DishVO dishVO = new DishVO();
                    BeanUtils.copyProperties(dish, dishVO);
                    // 将菜品数据保存到缓存中
                    //redisTemplate.opsForList().rightPush(key, JSON.toJSONString(dishVO));
                    return dishVO;
                }).collect(Collectors.toList());

        return collect;
    }

    /**
     * 根据条件查询菜品数据
     *
     * @param dish
     * @return
     */
    @Override
    public List<DishVO> listWithFlavor(Dish dish) {

        // 1.首先查询缓存中的菜品列表
        List<DishVO> collect = null;
        // 缓存中的Key
        String key = CacheConstants.DISH_LIST + dish.getCategoryId();
        List<String> range = redisTemplate.opsForList().range(key, 0, -1);
        if (CollUtil.isNotEmpty(range)) {
            return range.stream().map(s -> JSON.parseObject(s, DishVO.class)).collect(Collectors.toList());
        }

        // 2.查询菜品
        List<Dish> dishList = dishMapper.selectList(new LambdaQueryWrapper<Dish>()
                .eq(dish.getCategoryId() != null, Dish::getCategoryId, dish.getCategoryId())
                .eq(dish.getStatus() != null, Dish::getStatus, dish.getStatus())
                .like(dish.getName() != null, Dish::getName, dish.getName())
                .orderByDesc(Dish::getUpdateTime)
        );

        // 3.组合数据返回
        if (CollUtil.isNotEmpty(dishList)) {
            // 4.封装数据
            collect = dishList.stream().map(s -> {
                DishVO dishVO = new DishVO();
                BeanUtils.copyProperties(s, dishVO);
                // 5.查询菜品口味
                LambdaQueryWrapper<DishFlavor> df = new LambdaQueryWrapper<>();
                df.eq(DishFlavor::getDishId, s.getId());
                List<DishFlavor> dishFlavorList = dishFlavorService.list(df);
                dishVO.setFlavors(dishFlavorList);
                // 6.将数据保存到缓存中
                redisTemplate.opsForList().rightPush(key, JSON.toJSONString(dishVO));
                // 7.返回数据
                return dishVO;
            }).collect(Collectors.toList());
        }
        return collect;
    }
}
